﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Barbar.UrlGuard.Dal;
using Barbar.UrlGuard.Controls;
using Barbar.UrlGuard.BL;
using System.Globalization;
using System.Threading;

namespace Barbar.UrlGuard {
  public partial class FormAddOrEditUrlDialog : LocalizableForm, IInjector<MonitoringEntry>, ILocalizable {
    private string m_TitleEditing;
    private string m_TitleCreating;
    private string m_TestOK;
    private string m_TestError;
    private bool m_EditingMode = false;
    private bool m_TestPending = false;

    private void SetTitle() {
      if (m_EditingMode)
        Text = m_TitleEditing;
      else
        Text = m_TitleCreating;
    }

    public FormAddOrEditUrlDialog() {
      InitializeComponent();
    }

    private bool DoValidate() {
      if (string.IsNullOrEmpty(txtUrl.Text)) {
        errorProvider.SetError(txtUrl, "Url cannot be left empty.");
        return false;
      }

      try {
        Uri uri = new Uri(txtUrl.Text);
      } catch {
        errorProvider.SetError(txtUrl, "Url is not valid.");
        return false;
      }

      return true;
    }

    private void EnsureAuthentificationLookup() {
      if (cbxAuthentication.Items.Count == 0) {
        foreach (AuthenticationType authenticationType in AuthenticationType.GetAllTypes()) {
          cbxAuthentication.Items.Add(authenticationType);
        }
      }
    }

    private void btnOK_Click(object sender, EventArgs e) {
      if (DoValidate()) {
        errorProvider.Clear();
        DialogResult = DialogResult.OK;
        Close();
      }
    }

    private void LoadAuthData(AuthenticationBase authentication) {
      if (authentication == null)
        return;

      IInjectorUtility utility = ServiceLocator.Instance.Resolve<IInjectorUtility>();

      if (authentication.AuthenticationTypeID == AuthenticationType.None.AuthenticationTypeID) {
        return;
      }

      if (authentication.AuthenticationTypeID == AuthenticationType.Basic.AuthenticationTypeID) {
        utility.LoadData<AuthenticationBasic>((AuthenticationBasic)authentication, panAuth);
        return;
      }

      if (authentication.AuthenticationTypeID == AuthenticationType.NTLM.AuthenticationTypeID) {
        utility.LoadData<AuthenticationWindowsIntegrated>((AuthenticationWindowsIntegrated)authentication, panAuth);
        return;
      }

      throw new NotImplementedException();
    }

    #region IInjector<MonitoringEntry> Members

    public void SaveData(MonitoringEntry instance) {
      if (instance == null)
        throw new ArgumentNullException("instance");

      instance.Interval = (int)txtInterval.Value;
      instance.Url = txtUrl.Text;

      AuthenticationType authenticationType = (AuthenticationType)cbxAuthentication.SelectedItem;
      if (authenticationType.AuthenticationTypeID == AuthenticationType.None.AuthenticationTypeID) {
        instance.Authentication = null;
        return;
      }

      IInjectorUtility utility = ServiceLocator.Instance.Resolve<IInjectorUtility>();
      if (authenticationType.AuthenticationTypeID == AuthenticationType.Basic.AuthenticationTypeID) {
        AuthenticationBasic authenticationBasic = new AuthenticationBasic();
        utility.SaveData<AuthenticationBasic>(authenticationBasic, panAuth);
        instance.Authentication = authenticationBasic;
        return;
      }

      if (authenticationType.AuthenticationTypeID == AuthenticationType.NTLM.AuthenticationTypeID) {
        AuthenticationWindowsIntegrated authenticationWindowsIntegrated = new AuthenticationWindowsIntegrated();
        utility.SaveData<AuthenticationWindowsIntegrated>(authenticationWindowsIntegrated, panAuth);
        instance.Authentication = authenticationWindowsIntegrated;
        return;
      }

      throw new NotImplementedException();
    }

    #endregion

    #region IReadOnlyInjector<MonitoringEntry> Members

    public void LoadData(MonitoringEntry readOnlyInstance) {
      EnsureAuthentificationLookup();
      if (readOnlyInstance == null) {
        txtInterval.Value = 60;
        txtUrl.Text = string.Empty;
        cbxAuthentication.SelectedIndex = 0;
        m_EditingMode = false;
      } else {
        if (readOnlyInstance.Interval >= txtInterval.Minimum &&
          readOnlyInstance.Interval <= txtInterval.Maximum)
          txtInterval.Value = readOnlyInstance.Interval;
        else
          txtInterval.Value = 60;
        txtUrl.Text = readOnlyInstance.Url;
        if (readOnlyInstance.Authentication == null) {
          cbxAuthentication.SelectedIndex = 0;
        } else {
          int index = 0;
          foreach (AuthenticationType authenticationType in cbxAuthentication.Items) {
            if (authenticationType.AuthenticationTypeID == readOnlyInstance.Authentication.AuthenticationTypeID) {
              cbxAuthentication.SelectedIndex = index;
              break;
            }
            index++;
          }
          LoadAuthData(readOnlyInstance.Authentication);
        }
        m_EditingMode = true;
      }
      SetTitle();
    }

    #endregion

    #region ILocalizable Members

    public void Localize(ILocalizator localizator) {
      if (localizator == null)
        throw new ArgumentNullException("localizator");
 
      m_TitleCreating = localizator.Translate("FormAddOrEditUrlDialog_TitleCreate");
      m_TitleEditing = localizator.Translate("FormAddOrEditUrlDialog_TitleEdit");
      m_TestOK = localizator.Translate("FormAddOrEditUrlDialog_TestOK");
      m_TestError = localizator.Translate("FormAddOrEditUrlDialog_TestError");
      SetTitle();
    }

    #endregion

    private void cbxAuthentication_SelectedIndexChanged(object sender, EventArgs e) {
      authenticationBasicControl.Visible = false;
      authenticationWindowsIntegratedControl.Visible = false;

      AuthenticationType authentificationType = (AuthenticationType)cbxAuthentication.SelectedItem;
      if (authentificationType.AuthenticationTypeID == AuthenticationType.Basic.AuthenticationTypeID) {
        authenticationBasicControl.Visible = true;
      }
      if (authentificationType.AuthenticationTypeID == AuthenticationType.NTLM.AuthenticationTypeID) {
        authenticationWindowsIntegratedControl.Visible = true;
      }
    }

    private void btnTest_Click(object sender, EventArgs e) {
      if (DoValidate()) {
        if (m_TestPending) {
          return;
        }
        btnTest.Enabled = false;
        btnOK.Enabled = false;
        btnCancel.Enabled = false;
        m_TestPending = true;
        picLoading.Visible = true;
        MonitoringEntry entry = new MonitoringEntry();
        SaveData(entry);
        backgroundWorker.RunWorkerAsync(entry);
      }
    }

    private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) {
      MonitoringEntry entry = (MonitoringEntry)e.Argument;

      IWebRequestUtility webRequestUtility = ServiceLocator.Instance.Resolve<IWebRequestUtility>();
      webRequestUtility.CheckEntry(entry, 30000);

      e.Result = entry;
    }

    private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
      MonitoringEntry entry = (MonitoringEntry)e.Result;

      if (entry != null) {
        if (entry.Status.Value == MonitoringEntryStatus.OK.Value) {
          MessageBox.Show(m_TestOK);
        } else {
          MessageBox.Show(string.Format(CultureInfo.InvariantCulture, m_TestError, entry.LastStatusCode, entry.LastErrorMessage ?? @"N\A"));
        }
      }

      btnTest.Enabled = true;
      btnOK.Enabled = true;
      btnCancel.Enabled = true;
      picLoading.Visible = false;
      m_TestPending = false;
    }
  }
}
